import unittest
from typing import Any

from src.pipelines import Branch, Dispatch, Sequential


class Drop(object):
    def __call__(self, value: Any) -> None:
        pass


class Once(object):
    def __call__(self, value: int) -> int:
        return value


class Twice(object):
    def __call__(self, value: int) -> int:
        return value * 2


class TestPipeline(unittest.TestCase):
    def test_pipeline(self) -> None:
        pipeline = Sequential(
            Twice(),
            Dispatch(
                Once(),
                Twice(),
            ),
        )
        a, b = pipeline(1)
        self.assertEqual(a, 2)
        self.assertEqual(b, 4)

    def test_none_pipeline(self) -> None:
        pipeline = Sequential(
            Dispatch(
                Once(),
                Drop(),
                Twice(),
            )
        )
        a, c = pipeline(1)
        self.assertEqual(a, 1)
        self.assertEqual(c, 2)

    def test_branch(self) -> None:
        pipeline = Sequential(
            Branch(
                Twice(),  # The returned value will be ignored
            ),
            Once(),  # Receives the value returned by other pipelines before the branch
        )
        a = pipeline(1)
        self.assertEqual(a, 1)
